﻿using System;
using System.Collections.Generic;
using System.Text;

using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.Carto;
using PlanningGIS.Util.Convertor;
using PlanningGIS.ArcGIS;
using PlanningGIS.Util.Log;
using PlanningGIS.Engine.Controls;

namespace PlanningGIS.DataCheck.model
{
    /// <summary>
    /// 河流名称2、标示码2、上级河流名是否是否与上级河流相一致，要求：
    /// 本级河流名称2对应上级河流名称2
    /// 本级河流的上级河流名称对应上级河流名称
    /// 本级河流的标示码2对应上级河流的标识码
    /// </summary>
    public class HydName2Check:Check 
    {
        public int Check(string errType,IFeatureLayer pLyr,IGeometry pGeo,double buffer,string whereClause,string hydName,string hydName2,string superHydname,string hydCode,string hydCode2)
        {
            IFeatureClass pClass=pLyr.FeatureClass;
            if (pClass.ShapeType != esriGeometryType.esriGeometryPolyline)
            {
               LogHelper.WriteErrLog("【" + pLyr.Name + "】不是线图层，检查失败！");
                return -1;
            }
            int idxname = pClass.Fields.FindField(hydName);
            if (idxname == -1)
            {
               LogHelper.WriteErrLog("【"+pLyr.Name+"】中未找到河流名称【"+hydName+"】字段，检查失败！");
                return -1;
            }

            int idxname2 = pClass.Fields.FindField(hydName2);
            if (idxname2 == -1)
            {
               LogHelper.WriteErrLog("【" + pLyr.Name + "】中未找到河流名称2【" + hydName2 + "】字段，检查失败！");
                return -1;
            }

            int idxsupername = pClass.Fields.FindField(superHydname);
            if (idxsupername == -1)
            {
               LogHelper.WriteErrLog("【" + pLyr.Name + "】中未找到上级河流名称【" + superHydname + "】字段，检查失败！");
                return -1;
            }
            int idxcode = pClass.Fields.FindField(hydCode);
            if (idxcode == -1)
            {
               LogHelper.WriteErrLog("【" + pLyr.Name + "】中未找到河流标识码【" + hydCode + "】字段，检查失败！");
                return -1;
            }

            int idxcode2 = pClass.Fields.FindField(hydCode2);
            if (idxcode2 == -1)
            {
               LogHelper.WriteErrLog("【" + pLyr.Name + "】中未找到河流标识码2【" + hydCode2 + "】字段，检查失败！");
                return -1;
            }
            try
            {
                ISpatialFilter pSF = new SpatialFilterClass();
                if (pGeo != null)
                {
                    pSF.Geometry = pGeo;
                    pSF.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;
                    pSF.GeometryField = pClass.ShapeFieldName;
                }

                pSF.WhereClause = whereClause;
                showFakePro(true);
                LogHelper.WriteLog("正在计算需要检查的要素数目...");
                int max = FeatureClassHelper.GetFeatureCountFromLayer(pLyr, pSF);

                LogHelper.WriteLog("计算完毕，共有" + max + "个要素参与检查。");
                showFakePro(false);

                if (max == 0)
                {
                    LogHelper.WriteLog("没有满足检查要求的要素存在。");
                    return -1;
                }

                setProcessBarMax(max);

                IFeatureCursor pFeatureCursor = pLyr.Search(pSF, false);
                IFeature pFeature;
                int count = 0;
                int errCount = 0;
                while ((pFeature = pFeatureCursor.NextFeature()) != null)
                {
                    if (IsStop()) { break; }
                    count++;
                    setProcessBarCurrent(count);
                    IPolyline pLine = pFeature.Shape as IPolyline;
                    IPoint toPoint = pLine.ToPoint;
                    bool hasSuper = HasSuperhydByPoint(toPoint, pFeature, errType, pLyr, buffer, idxname, idxname2, idxsupername, idxcode, idxcode2, ref errCount);
                    if (!hasSuper)
                    {
                        toPoint = pLine.FromPoint;
                        HasSuperhydByPoint(toPoint, pFeature, errType, pLyr, buffer, idxname, idxname2, idxsupername, idxcode, idxcode2, ref errCount);
                    }
                }
                finishPro.Invoke();

                DataCheckUtility.ReleaseComObject(pFeatureCursor);

                LogHelper.WriteLog(errType + "检查结束。共发现" + errCount + "处错误！\n");
                return errCount;
            }
            catch
            {
                return -1;
            }
        }

        private bool HasSuperhydByPoint(IPoint pPoint, IFeature pFeature,string errType, IFeatureLayer pLyr,double buffer, int indexname, int indexname2, int indexsupername, int indexcode, int indexcode2,ref int errCount)
        {
            try
            {
                IPolygon pTempGeo = GeometryHelper.GetBuffer(pPoint, buffer, (pLyr.FeatureClass as IGeoDataset).SpatialReference) as IPolygon;// pTopo.Buffer(buffer) as IPolygon;
                ISpatialFilter psf = new SpatialFilterClass();
                psf.Geometry = pTempGeo;
                psf.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;
                int count = pLyr.FeatureClass.FeatureCount(psf);
                if (count == 0)
                {
                    return false;
                }
                IFeatureCursor pCursor = pLyr.Search(psf, false);
                IFeature pSuperFeature;
                bool isSuperHyd = false;
                while ((pSuperFeature = pCursor.NextFeature()) != null)
                {
                    bool isCorrect = SuperHydByRelation(pSuperFeature, pTempGeo);
                    if (!isCorrect) { continue; }
                    isCorrect = Name2NotSameTwoFeatures(pFeature, pSuperFeature, indexname, indexname2, indexsupername, indexcode, indexcode2);
                    if (!isCorrect) { continue; }
                    isSuperHyd = true;
                    string currentName2 = StringHelper.ConvertWRTNull(pFeature.get_Value(indexname2));
                    string currentSupername = StringHelper.ConvertWRTNull(pFeature.get_Value(indexsupername));
                    string currentCode2 = StringHelper.ConvertWRTNull(pFeature.get_Value(indexcode2));

                    string superName = StringHelper.ConvertWRTNull(pSuperFeature.get_Value(indexname));
                    string superName2 = StringHelper.ConvertWRTNull(pSuperFeature.get_Value(indexname2));
                    string superCode = StringHelper.ConvertWRTNull(pSuperFeature.get_Value(indexcode));
                    if (currentName2 != superName2)
                    {
                        RecordListHelper.AddRecordItem(errType, pLyr, null, pFeature, pSuperFeature, pPoint, "河流的名称2与上级河流的名称2不一致");
                        errCount++;
                        continue;
                    }
                    if (currentSupername != superName)
                    {
                        RecordListHelper.AddRecordItem(errType, pLyr, null, pFeature, pSuperFeature, pPoint, "河流的上级河流名与上级河流的名称不一致");
                        errCount++;
                        continue;
                    }
                    if (currentCode2 != superCode)
                    {
                        RecordListHelper.AddRecordItem(errType, pLyr, null, pFeature, pSuperFeature, pPoint, "河流的标示码2与上级河流的标示码不一致");
                        errCount++;
                        continue;
                    }
                }
                DataCheckUtility.ReleaseComObject(pCursor);
                return isSuperHyd;
            }
            catch
            {
                return false;
            }
        }

        //从属性字段的角度判断是否是上级河流名
        private bool Name2NotSameTwoFeatures(IFeature pCurrentFeat, IFeature pSuperFeat, int indexname, int indexname2, int indexsupername, int indexcode, int indexcode2)
        {
            string currentName2 = StringHelper.ConvertWRTNull(pCurrentFeat.get_Value(indexname2));
            string currentSupername = StringHelper.ConvertWRTNull(pCurrentFeat.get_Value(indexsupername));
            string currentCode2 = StringHelper.ConvertWRTNull(pCurrentFeat.get_Value(indexcode2));

            string superName = StringHelper.ConvertWRTNull(pSuperFeat.get_Value(indexname));
            string superName2 = StringHelper.ConvertWRTNull(pSuperFeat.get_Value(indexname2));
            string superCode = StringHelper.ConvertWRTNull(pSuperFeat.get_Value(indexcode));
            string superSupername = StringHelper.ConvertWRTNull(pSuperFeat.get_Value(indexsupername));
            string superCode2 = StringHelper.ConvertWRTNull(pSuperFeat.get_Value(indexcode2));

            int currentNameNum = currentName2.Length;
            int currentSuperNum = currentSupername.Length;
            int currentCode2Num = currentCode2.Length;

            if (pSuperFeat.OID == pCurrentFeat.OID)
            {
                return false;
            }

            //当前要素的名称2、标识码2、上级河流名都为空，就假定是其河流名
            if (currentCode2Num == 0 && currentNameNum == 0 && currentSuperNum == 0)
            {
                return true;
            }
            //如果两个要素的分类代码2相同，判定为两者是具有同一各上级河流名的要素
            if (currentCode2Num >0 && currentCode2 == superCode2)
            {
                return false ;
            }

            //如果两个要素的上级河流名相同，判定为两者是具有同一各上级河流名的要素
            if (currentSuperNum > 0 && currentSupername == superSupername)
            {
                return false ;
            }

            if (currentName2 != superName2)
            {
                return true ;
            }
            if (currentSupername != superName)
            {
                return true;
            }

            if (currentCode2 != superCode)
            {
                return true;
            }
            return false ;
        }

        //从图形角度判断是否是上级河流
        private bool SuperHydByRelation(IFeature pFeature,IPolygon pPolygon)
        {
            try
            {
                IPolyline pPl = pFeature.ShapeCopy as IPolyline;
                IRelationalOperator pRela = pPolygon as IRelationalOperator;
                if (pRela.Crosses(pPl))
                {
                    if (pRela.Contains(pPl.ToPoint ))
                    {
                        return false ;
                    }
                    else
                    {
                        return true ;
                    }
                }
                return false ;
            }
            catch
            { 
                return false; 
            }
        }


    }
}
